+function ($) {

    /**
     * 定义基础内部全局变量
     */
    var
        /**
         * 当前window对象
         * @type {jQuery Object}
         */
        $win = $(window),

        /**
         * 当前document对象
         * @type {jQuery Object}
         */
        $doc = $(document),

        /**
         * ThinkEditor 对象
         * @type {Object}
         */
        ThinkEditor,

        /**
         * 封装过的textarea Range对象
         * @type {Object}
         */
        Range,

        /**
         * 编辑器弹出层对象
         * 主要提供给一些需要复杂功能的插件使用
         * 在插件中使用 this.dialog()方法调用
         * @type {Object}
         */
        Dialog,

        /**
         * ThinkEditor插件对象，所有的操作都是通过该对象实现
         * @type {Object}
         */
        Plugin = {},

        /**
         * ThinkEditor语言包对象
         */
        Language = {},

        /**
         * 键盘按键对应数值表
         * @type {Object}
         */
        KeyCode = {
            "BACKSPACE": 8,
            "TAB": 9,
            "ENTER": 13,
            "ESC": 27,
            "SPACE": 32,
            "F1": 112,
            "F2": 113,
            "F3": 114,
            "F4": 115,
            "F5": 116,
            "F6": 117,
            "F7": 118,
            "F8": 119,
            "F9": 120,
            "F10": 121,
            "F11": 122,
            "F12": 123
        },

        /**
         * 默认配置项，创建Tree时传入的配置项会和该配置合并
         * @type {Object}
         */
        Defaults = {
            /**
             * 显示风格
             * 目前仅支持默认风格，可自己扩展
             */
            "style": "default",

            /**
             * 编辑器插件按钮配置
             * 没配置到这里的插件不能显示在工具栏
             * 如果设置了快捷键依然生效
             */
            "items": "h1,h2,h3,h4,h5,h6,-,link,image,-,bold,italic,code,-," +
            "ul,ol,blockquote,hr,-,fullscreen,save",

            /**
             * 编辑器默认宽度
             * 默认自适应父容器
             */
            "width": "100%",

            /**
             * 编辑器高度，默认自适应父容器
             * 设置为100%时一定要给父元素设置高度
             */
            "height": "100%",

            /**
             * 编辑器显示语言
             * 目前仅支持简体中文和英文
             * 可以在调用编辑器之前调用$.thinkeditor.language方法扩展
             */
            "lang": "zh-cn",

            /**
             * 按TAB键插入的字符
             * 默认为四个空格，一般情况下为空格或制表符
             * 插入制表符请写 \t
             */
            "tab": "    ",

            /**
             * 图片上传插件上传到的URL
             * 该URL必须返回JSON数据
             * 数据格式：
             * {
         *     "status" : 1,
         *     "info"   : "message",
         *     "files"  : [] //文件信息
         * }
             */
            "uploader": "",

            /**
             * 图片上传表单名称
             * 即<input type="file" name=""/>name属性默认设置的值
             */
            "dataName": "images",

            /**
             * 保存按钮点击后调用的回调函数
             */
            "onSave": $.noop //保存按钮回调接口
        },

        DialogWraper = [
            '<div class="thinkeditor-dialog">',
            '<div class="thinkeditor-dialog-header">',
            '<span class="thinkeditor-dialog-title"></span>',
            '<span class="thinkeditor-dialog-close"></span>',
            '</div>',
            '<div class="thinkeditor-dialog-body"></div>',
            '<div class="thinkeditor-dialog-footer">',
            '<div class="thinkeditor-dialog-status"></div>',
            '<div class="thinkeditor-dialog-tools">',
            '<button type="button" class="thinkeditor-dialog-btn-ok"></button>',
            '<button type="button" class="thinkeditor-dialog-btn-cancel"></button>',
            '</div>',
            '</div>',
            '</div>'
        ].join("");

    /**
     * Range构造器，用于创建一个新的Range对象
     * @param {Object} textarea 一个textarea对象，用于创建Range
     */
    Range = function (textarea) {
        /* 绑定Range对象的textarea */
        this.textarea = textarea;
    }

    /**
     * 扩展Range原型，主要添加了get,set,insert三个方法
     * @type {Object}
     */
    Range.prototype = {
        /**
         * 获取当前range
         * @return {Object} 当前range对象
         */
        "get": function () {
            var textarea = this.textarea,
                data = {"start": 0, "end": 0, "text": ""},
                range, dupRange, rangeNl, dupRangeNl;

            textarea.focus();
            if (textarea.setSelectionRange) { // W3C
                data.start = textarea.selectionStart;
                data.end = textarea.selectionEnd;
                data.text = (data.start != data.end) ?
                    textarea.value.substring(data.start, data.end) : "";
            } else if (document.selection) { // For IE
                range = document.selection.createRange(),
                    dupRange = range.duplicate();
                dupRange.moveToElementText(textarea);
                dupRange.setEndPoint("EndToEnd", range);

                data.text = range.text; //选中的文本内容
                rangeNl = range.text.split("\n").length - 1; //选中文本换行数
                dupRangeNl = dupRange.text.split("\n").length - 1; //选中之前换行数
                data.start = dupRange.text.length - range.text.length -
                dupRangeNl + rangeNl;
                data.end = data.text.length + data.start - rangeNl;
            }

            return data;
        },

        /**
         * 设置当前range的位置
         * @param  {Integer} start 起始位置
         * @param  {Integer} end   结束位置
         * @return {Object}        当前Range对象
         */
        "set": function (start, end) {
            var range, textarea = this.textarea;

            textarea.focus();
            if (textarea.setSelectionRange) { // W3C
                textarea.setSelectionRange(start, end);
            } else if (textarea.createTextRange) { // For IE
                range = textarea.createTextRange();
                range.collapse(true);
                range.moveStart("character", start);
                range.moveEnd("character", end - start);
                range.select();
            }

            return this;
        },

        /**
         * 在当前Range处插入文本
         * @param  {String} text 文本内容
         * @return {Object}      当前Range对象
         */
        "insert": function (text) {
            var textarea = this.textarea, data = this.get(),
                oValue, nValue, range, scroll;

            if (textarea.setSelectionRange) { // W3C
                oValue = textarea.value;
                nValue = oValue.substring(0, data.start) + text +
                oValue.substring(data.end);
                scroll = textarea.scrollTop;
                data.end = data.start + text.length;
                textarea.value = nValue;

                /**
                 * Fixbug:
                 * After textarea.values = nValue, scrollTop value to 0
                 */
                if (textarea.scrollTop != scroll) {
                    textarea.scrollTop = scroll;
                }

                textarea.setSelectionRange(data.start, data.end);
            } else if (textarea.createTextRange) { //For IE
                range = document.selection.createRange();
                range.text = text;
                range.setEndPoint("StartToEnd", range);
                range.select();
            }

            return this;
        }
    };

    /**
     * 简单的弹出层对象，供需要弹出显示的插件调用
     * @param {Object} editor  编辑器对象
     * @param {Object} options 编辑器配置对象
     */
    Dialog = function (editor, options) {
        var self = this, $dialog, $modal, defaults,
            $editor = $(editor.range.textarea).closest(".thinkeditor");

        /* 弹出层默认配置 */
        defaults = {
            "title": "title",
            "content": "<div></div>",
            "onOkClick": $.noop,
            "onCancelClick": $.noop
        }

        //合并配置并创建弹出层
        options = $.extend({}, defaults, options || {});

        /* 创建弹出层内容区 */
        this.dialog = $dialog = $(DialogWraper).appendTo($editor);
        //创建遮罩层
        this.modal = $modal = $("<div/>").addClass("thinkeditor-dialog-modal")
            .appendTo($editor);

        /* 弹出层相关容器 */
        this.title = $dialog.find(".thinkeditor-dialog-title"); //标题
        this.content = $dialog.find(".thinkeditor-dialog-body"); //内容
        this.status = $dialog.find(".thinkeditor-dialog-status"); //状态信息

        /* 弹出层按钮 */
        this.btn = {
            "close": $dialog.find(".thinkeditor-dialog-close"),
            "ok": $dialog.find(".thinkeditor-dialog-btn-ok"),
            "cancel": $dialog.find(".thinkeditor-dialog-btn-cancel")
        }

        /* 绑定关闭事件 */
        this.btn.close.click(function () {
            self.remove();
        });

        /* 绑定确定按钮事件 */
        this.btn.ok.click(function () {
            options.onOkClick.call(self, this);
        });

        /* 绑定取消按钮事件 */
        this.btn.cancel.click(function () {
            options.onCancelClick.call(self, this);
            self.remove();
        });

        //添加弹出层内容并
        this.setTitle(options.title);
        this.setContent(options.content);
        this.btn.ok.text(editor.lang("ok"));
        this.btn.cancel.text(editor.lang("cancel"));

        //显示弹出层
        $dialog.add($modal).fadeIn("fast");
    }

    /**
     * 弹出层标准接口
     * @type {Object}
     */
    Dialog.prototype = {
        /**
         * 查找弹出层内容里的元素
         * @param  {String} expr jQuery支持的所有选择器
         * @return {Object}      jQuery对象
         */
        "find": function (expr) {
            return this.content.find(expr);
        },

        /**
         * 移动弹出层到屏幕中央
         * @return {Object} 弹出层对象
         */
        "moveToCenter": function () {
            this.dialog.css({
                "top": ($win.height() - this.dialog.outerHeight()) / 2,
                "left": ($win.width() - this.dialog.outerWidth()) / 2
            });
            return this;
        },

        /**
         * 重置弹出层内容
         * @param  {Object} content 弹出层内容对象，可以是html代码
         * @return {Object}         弹出层对象
         */
        "setContent": function (content) {
            this.content.empty().append(content);
            this.moveToCenter();
            return this;
        },

        /**
         * 改变弹出层标题
         * @param  {String} title 弹出层标题文字，可以是html代码
         * @return {Object}       弹出层对象
         */
        "setTitle": function (title) {
            return this.title.html(title);
        },

        /**
         * 设置弹出层状态信息
         * @param  {String}  info   状态信息
         * @param  {String}  status 状态标识，success，error
         * @param  {Boolean} dealy  是否自动关闭
         * @return {Object}         当前弹出层对象
         */
        "setStatus": function (info, status, dealy) {
            var $status = $("<span/>").text(info), timeout;

            /* 清楚原来计时器 */
            timeout = this.status.children("span").data("timeout");
            timeout && clearTimeout(timeout);

            /* 显示状态信息 */
            status && $status.addClass("thinkeditor-dialog-" + status);
            this.status.empty().append($status);

            /* 延时关闭 */
            if (dealy) {
                $status.data("timeout", setTimeout(function () {
                    $status.fadeOut("fast");
                }, 5000));
            }
            return this;
        },

        /**
         * 卸载当前弹出层
         */
        "remove": function () {
            this.dialog.add(this.modal).fadeOut("fast", function () {
                this.remove();
            });
        }
    };

    /**
     * 创建编辑器工具栏
     * @param  {Object} $editor 编辑器对象
     * @param  {Object} options 配置项
     */
    function create_editor_tools($editor, options) {
        var self = this, items, groups = options.items.split(",-,"), $group,
            $tools = $("<div/>");

        /* 创建按钮组 */
        for (i in groups) {
            items = groups[i].split(",");
            $group = $("<div/>").addClass("thinkeditor-tools-group")
                .appendTo($tools);
            for (j in items) {
                $("<a/>").addClass("thinkeditor-tools-" + items[j])
                    .attr({"title": this.lang(items[j]), "href": "javascript:;"})
                    .data("name", items[j])
                    .appendTo($group);
            }
        }

        /* 工具栏放入editor */
        $tools.addClass("thinkeditor-tools clearfix").prependTo($editor);

        /* 绑定操作事件 */
        $tools.on("click", ".thinkeditor-tools-group a", function (event) {
            event.stopPropagation();
            self.plugin($(this).data("name"), options);
        });
    }

    /**
     * 执行快捷键
     * @param  {event} event 事件对象
     */
    function keyboard(event) {
        var keyboard = Array(4),
            self = event.data.self,
            options = event.data.options;

        /* 当前按键 */
        keyboard[0] = event.ctrlKey ? "ctrl" : "";
        keyboard[1] = event.shiftKey ? "shift" : "";
        keyboard[2] = event.altKey ? "alt" : "";
        keyboard[3] = event.which;
        keyboard = keyboard.join("");

        /* 执行快捷键 */
        if (self.keyboards[keyboard]) {
            if ($.isFunction(self.keyboards[keyboard])) {
                self.keyboards[keyboard].call(self);
            } else {
                self.plugin(self.keyboards[keyboard], options);
            }
            return false;
        }
    }

    /**
     * 编辑器构造器，用于创建一个新的编辑器对象
     * @param {Object} textarea 被创建编辑器的textarea对象
     * @param {Object} options  编辑器初始化选项
     */
    ThinkEditor = function (textarea, options) {
        var options, self = this, $textarea = $(textarea), $editor;

        /* 合并配置项 */
        options = $.extend({}, Defaults, options || {});
        options.width = options.width ? options.width : $textarea.width();
        options.height = options.height ? options.height : $textarea.height();

        /* 创建Range对象 */
        this.range = new Range(textarea);
        this.language = Language[options.lang] ? options.lang : "en-us";

        /* 创建编辑器 */
        $textarea.wrap("<div/>").parent().wrap("<div/>");
        $editor = $textarea.parent().parent();

        $editor.addClass("thinkeditor thinkeditor-" + options.style);
        $editor.children("div").addClass("thinkeditor-textarea");
        //如果是预览创建预览div
        if (options.preview) {
            options.width = '50%';
            $textarea.parent().after('<div/>');
            $textarea.css({resize: 'none'});
            $preview = $editor.find('.thinkeditor-textarea').next('div');
        }
        /* 设置editor尺寸 */
        $editor.css({"width": options.width, "height": options.height});

        /* 创建工具栏 */
        create_editor_tools.call(this, $editor, options);

        /* 绑定快捷键事件 */
        $textarea.keydown({"self": this, "options": options}, keyboard);

        /* 绑定插件的快捷键 */
        for (name in Plugin) {
            Plugin[name].keyboard && this.keyboard(Plugin[name].keyboard, name);
        }
        if (options.preview) {
            $preview.css({
                "width": '100%',
                "height": $textarea.outerHeight(true) + 'px',
                left: '100%'
            });
            $preview.addClass('thinkeditor-preview');

            $preview.html(this.preview(this.range.textarea.value));
            _this = this;
            $textarea.keyup(function () {
                $preview.html(_this.preview(this.value));
            });
            $textarea.scroll(function () {
                fix_img_scroll();
            });
            var fix_img_scroll = function () {
                imgs = $preview.find("img") //获取预览下所有图片
                if (imgs.length > 0) {
                    imgs_height = 0
                    for (var i in imgs) {
                        tm = new Image()
                        tm.src = this.src
                        tow = tm.width
                        toh = tm.height
                        var limit_width = $preview.width() * 0.5 //父容器50%的宽度
                        if (tow > limit_width) { //如果原始图片宽度大于限制宽度，真实rh高度也要缩放比例
                            r = tow / limit_width
                            rh = toh / r
                        } else {
                            rh = toh
                        }
                        imgs_height += rh //这个就是得到所有图片的高度
                    }
                }
                caculate_and_scroll($textarea, $preview, imgs_height);
            }

            var caculate_and_scroll = function (editor, preview, imgs_height) { //这里只要再按比例计算一下滚动高度就行
                real_height = preview[0].scrollHeight + imgs_height;

                setTimeout(function () {
                    if (real_height > editor[0].scrollHeight) {
                        r = real_height / editor[0].scrollHeight;
                        preview.prop('scrollTop', editor.scrollTop() * r);
                    } else {
                        r = editor[0].scrollHeight / real_height;
                        preview.prop('scrollTop', editor.scrollTop() / r);
                    }
                }, 500);
            }
        }

    }

    /**
     * 编辑器原型，用于扩展编辑器的外部调用接口
     * @type {Object}
     */
    ThinkEditor.prototype = {
        /**
         * 获取语言变量
         * @param  {String} name     变量名
         * @param  {String} language 语言，默认去当前options.lang
         * @return {String}          指定语言的值
         */
        "lang": function (name, language) {
            return Language[language || this.language][name] || name;
        },

        /**
         * 执行某个插件插件
         * @param {String} name    插件名称
         * @param {Object} options 编辑器配置项
         */
        "plugin": function (name, options) {
            var plugin = Plugin[name]
            plugin.markdown.call(this, options, plugin);
            return this;
        },

        /**
         * 插入数据到编辑器光标处
         * @param  {String} text 要插入的数据
         * @return {Object}      ThinkEditor对象
         */
        "insert": function (text) {
            var range = this.range.get(), start, _start, end, length, line = 0;
            if (arguments.length > 1) { //首尾添加文本
                start = arguments[0];
                end = arguments[1];

                if (arguments[2]) { //按行添加
                    text = range.text.split("\n");
                    length = range.text.length;

                    /* 逐行添加 */
                    for (i in text) {
                        if (!length || $.trim(text[i])) {
                            _start = start.replace("{$line}", ++line)
                                .replace("{$i}", i);
                            text[i] = _start + text[i] + end;
                        }
                    }

                    /* 插入数据 */
                    this.range.insert(text.join("\n"));

                    /* 没有选中文本时设置光标位置 */
                    if (!length) {
                        start = range.start + _start.length;
                        this.range.set(start, start);
                    }
                } else {
                    this.range.insert(start + range.text + end);
                }
            } else { //插入文本
                this.range.insert(text);
            }
            return this;
        },

        /**
         * 设置或获取编辑器的值
         * @param  {String} text 要设置的值，不传递此参数则获取编辑器的值
         * @return {String}      设置值 - 返回ThinkEditor对象， 获取值 - 返回当前值
         */
        "value": function (text) {
            if (text === undefined) {
                return this.range.textarea.value;
            } else {
                this.range.textarea.value = text;
                return this;
            }
        },

        /**
         * 给编辑器绑定快捷键
         * @param  {String}   keys     快捷键名称
         * @param  {Function} callback 触发快捷键时执行额函数或插件名称
         * @return {Object}            当前编辑器对象
         */
        "keyboard": function (keys, callback) {
            var keyboard = Array(4); //[ctrl, shift, alt, code]

            //初始化快捷键
            if (!this.keyboards) {
                this.keyboards = {};
            }

            keys = keys.toUpperCase().split("+");
            for (i in keys) {
                switch (keys[i]) {
                    case "CTRL" :
                        keyboard[0] = "ctrl";
                        break;
                    case "SHIFT" :
                        keyboard[1] = "shift";
                        break;
                    case "ALT" :
                        keyboard[2] = "alt";
                        break;
                    default:
                        keyboard[3] = KeyCode[keys[i]] || keys[i].charCodeAt();
                        break;
                }
            }
            this.keyboards[keyboard.join("")] = callback;
            return this;
        },

        "dialog": function (options) {
            return new Dialog(this, options);
        },
        "preview": function (text) {
            var opt = {
                renderer: new marked.Renderer(),
                gfm: true,
                tables: true,
                breaks: false,
                pedantic: false,
                sanitize: true,
                smartLists: true,
                smartypants: false
            }
            return marked(text, opt);
        }
    }

    /**
     * 通过textarea获取通过当前textarea创建的ThinkEditor对象
     * @param  {elements} textarea textarea对象或jquery textarea选择器
     * @return {Object}            ThinkEditor对象
     */
    $.thinkeditor = function (textarea) {
        return $(textarea).data("ThinkEditor");
    };

    /**
     * 添加ThinkEditor全局扩展
     * 提供对编辑器的语言包，插件，全局设置等功能
     */
    $.extend($.thinkeditor, {
        /**
         * 扩展语言包
         * @param  {Object} language 语言包
         */
        "language": function (language) {
            $.extend(Language, $.isPlainObject(language) ? language : {});
        },

        /**
         * 扩展插件
         * @param  {Object} plugin 一个或多个插件
         */
        "plugin": function (plugin) {
            $.extend(Plugin, $.isPlainObject(plugin) ? plugin : {});
        },

        /**
         * 全局设置ThinkEditor
         * @param  {Object} options 要改变的编辑器默认设置项
         */
        "defaults": function (options) {
            $.extend(Defaults, $.isPlainObject(options) ? options : {});
        }
    });

    /**
     * jQuery.fn对象，用于创建ThinkEditor插件
     * @param  {Object} options ThinkEditor初始化参数
     */
    $.fn.thinkeditor = function (options) {
        return this.each(function () {
            $(this).data("ThinkEditor", new ThinkEditor(this, options));
        });
    }

    /**
     * ThinkEditor编辑器插件，工具按显示的每一个按钮代表一个插件
     * 一个合法的插件必须包含markdown方法，用于内部调用
     * 如果需要给插件设置快捷键，则可以通过 keyboard 属性来设置
     * 插件的this指针指向当前ThinkEditor对象
     */
    $.thinkeditor.plugin({
        /* 标题一插件 */
        "h1": {
            /* 标题一快捷键 */
            "keyboard": "ctrl+1",

            /* 执行标题一 */
            "markdown": function (options) {
                this.insert("# ", "", true);
            }
        },

        /* 标题二插件 */
        "h2": {
            /* 标题二快捷键 */
            "keyboard": "ctrl+2",

            /* 执行标题二 */
            "markdown": function (options) {
                this.insert("## ", "", true);
            }
        },

        /* 标题三插件 */
        "h3": {
            /* 标题三快捷键 */
            "keyboard": "ctrl+3",

            /* 执行标题三 */
            "markdown": function (options) {
                this.insert("### ", "", true);
            }
        },

        /* 标题四插件 */
        "h4": {
            /* 标题四快捷键 */
            "keyboard": "ctrl+4",

            /* 执行标题四 */
            "markdown": function (options) {
                this.insert("#### ", "", true);
            }
        },

        /* 标题五插件 */
        "h5": {
            /* 标题五快捷键 */
            "keyboard": "ctrl+5",

            /* 执行标题五 */
            "markdown": function (options) {
                this.insert("##### ", "", true);
            }
        },

        /* 标题六插件 */
        "h6": {
            /* 标题六快捷键 */
            "keyboard": "ctrl+6",

            /* 执行标题六 */
            "markdown": function (options) {
                this.insert("###### ", "", true);
            }
        },

        /* 添加链接 */
        "link": {
            /* 连接快捷键 */
            "keyboard": "ctrl+l",

            /* 插入连接 */
            "markdown": function (options) {
                var range = this.range.get(), start;

                if (range.text.length) {
                    if (range.text.match(/^http:\/\/.*/i)) {
                        this.insert("[" + range.text + "](" + range.text + ")");
                    } else {
                        this.insert("[" + range.text + "]()");
                        start = range.start + range.text.length + 3;
                        this.range.set(start, start);
                    }
                } else {
                    this.insert("[]()");
                    start = range.start + 1;
                    this.range.set(start, start);
                }
            }
        },

        /* 添加图片 */
        "image": {
            /* 图片快捷键 */
            "keyboard": "ctrl+p",

            /* 插入图片 */
            "markdown": function (options, self) {
                var $text, drop, dialog, start,
                    editor = this,
                    range = this.range.get();

                /* 当选中文本是远程图片URL时不弹出上传层 */
                if (range.text.length && range.text.match(/^http:\/\/.*/i)) {
                    this.insert("![ALT](" + range.text + ")");
                    start = range.start + 2;
                    this.range.set(start, start + 3);
                    return;
                }

                //拖动上传容器
                $text = $("<span/>").text(this.lang("image-text"));
                self.drop = drop = $("<div/>").addClass("thinkeditor-plugin-image")
                    .append($text);

                //弹出图片上传层
                self.dialog = dialog = this.dialog({
                    "title": this.lang("image-title"),
                    "content": drop,
                    "onOkClick": function () {
                        self.upload(editor, options)
                    }
                });

                /* 初始化数据对象 */
                self.data = new FormData();
                //初始化文件数
                self.data.length = 0;

                /* 绑定drag事件，主要是用来设置文件放置框的样式 */
                drop.on("dragenter dragleave", function (event) {
                    drop.toggleClass("thinkeditor-image-draghover");
                    event.stopPropagation();
                    return false;
                });

                /* 文件拖动事件，不绑定该事件 drop 事件不生效 */
                drop.on("dragover", function () {
                    return false
                });

                /**
                 * 文件拖动结束事件
                 * 该事件必须用原生方式绑定，拖动结束后浏览器会自动跳转到图片预览页面
                 * ？暂不明白是什么原因
                 */
                drop[0].addEventListener("drop", function (event) {
                    var files = event.target.files || event.dataTransfer.files;

                    if (!files) return; //不支持文件拖动

                    /* 取消拖动样式，阻止事件冒泡及默认事件 */
                    drop.removeClass("thinkeditor-image-draghover");
                    event.stopPropagation();
                    event.preventDefault();

                    //上传文件
                    self.show(files, options);
                }, false);
            },

            /**
             * 将上传好的图片插入到编辑器
             * @param  {Array}  imgs   上传的图片数组
             * @param  {Object} editor 图片对象
             */
            "insert": function (imgs, editor) {
                var range = editor.range.get(), img, alt, src, text = [];

                for (name in imgs) {
                    img = imgs[name];
                    alt = range.text.length ? range.text : img.name.split(".")[0];
                    src = img.rootpath + img.savepath + img.savename;
                    text.push("![" + alt + "](" + src + ")");
                }

                editor.insert(text.join("\n"));
                text = text[0];
                editor.range.set(range.start + 2, range.start + text.indexOf("]"));
            },

            /**
             * 预览选择的图片
             * @param  {Object} files   选择的图片对象
             * @param  {Object} options 编辑器配置对象
             */
            "show": function (files, options) {
                var data = this.data, msg;

                for (var i = 0, file; file = files[i]; i++) {
                    //禁止上传非图片文件
                    if (!file.type.match(/^image\/(?:png|jpeg|jpg|gif)$/)) {
                        msg = "忽略非图片文件：" + file.name;
                        this.dialog.setStatus(msg, "error", true);
                    } else if (file.size > 1024 * 1024 * 10) {
                        msg = "忽略超过大小限制的图片：" + file.name;
                        this.dialog.setStatus(msg, "error", true);
                    } else {
                        if (data.length < 3) {
                            data.append(options.dataName + i, file);
                            data.length++;
                            this.reader(file);
                        } else {
                            msg = "最多同时上传3张图片，";
                            msg += "已忽略" + (files.length - i) + "张";
                            this.dialog.setStatus(msg, "error", true);
                            break;
                        }
                    }
                }
            },

            /**
             * 读取图片数据以提供预览
             * @param  {Object} file 图片对象
             */
            "reader": function (file) {
                var self = this, reader = new FileReader(); //初始化文件对象

                /* 展示选择的图片 */
                reader.onload = function () {
                    var html = [
                        "<div>", //用于浮动
                        "<span>", //再添加一层标签主要是为了解决图片垂直居中
                        "<img src=\"" + this.result + "\">",
                        "</span>",
                        "</div>"
                    ].join("");
                    self.drop.append(html);
                }
                reader.readAsDataURL(file);
            },

            /**
             * AJAX上传图片，只有支持HTML的浏览器才能支持该方法
             * @param  {Object} editor  编辑器对象
             * @param  {Object} options 编辑器配置对象
             */
            "upload": function (editor, options) {
                var self = this, xhr = new XMLHttpRequest(), msg;
                if (!xhr.upload) {
                    msg = "您的浏览器不支持ajax上传文件！";
                    this.dialog.setStatus(msg, "error", true);
                    return;
                }

                // 上传中
                xhr.upload.addEventListener("progress", function (event) {
                    var progress = Math.round(event.loaded / event.total);
                    msg = "正在上传图片..." + progress + "%";
                    self.dialog.setStatus(msg, "success");
                }, false);

                // 文件上传成功或是失败
                xhr.onreadystatechange = function () {
                    var data, images = [];
                    if (xhr.readyState == 4) {
                        if (xhr.status == 200) {
                            data = $.parseJSON(xhr.responseText);
                            if (data.status) {
                                self.insert(data.files, editor);
                                self.dialog.remove();
                            } else {
                                self.dialog.setStatus(data.info, "error", true);
                            }
                        } else {
                            self.dialog.setStatus("图片上传失败！", "error", true);
                        }
                    }
                };

                // 开始上传
                this.dialog.setStatus("正在上传图片...0%", "success");
                xhr.open("POST", options.uploader, true);
                xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
                xhr.send(this.data);
            }

        },

        /* 文本加粗插件 */
        "bold": {
            /* 文本加粗快捷键 */
            "keyboard": "ctrl+b",

            /* 执行文本加粗 */
            "markdown": function (options) {
                this.insert("**", "**", true);
            }
        },

        /* 文字倾斜插件 */
        "italic": {
            /* 文字倾斜快捷键 */
            "keyboard": "ctrl+i",

            /* 执行文字倾斜 */
            "markdown": function (options) {
                this.insert("_", "_", true);
            }
        },

        /* 插入代码 */
        "code": {
            /* 代码快捷键 */
            "keyboard": "ctrl+d",

            /* 插入代码 */
            "markdown": function (options) {
                var range = this.range.get(), start;

                if (range.text.length) {
                    if (range.text.split("\n").length > 1) {
                        this.insert("~~~\n" + range.text + "\n~~~");
                        start = range.start + 3;
                        this.range.set(start, start);
                    } else {
                        this.insert("`" + range.text + "`");
                    }
                } else {
                    this.insert("``");
                    start = range.start + 1;
                    this.range.set(start, start);
                }
            }
        },

        /* 无序列表插件 */
        "ul": {
            /* 代码快捷键 */
            "keyboard": "ctrl+u",

            /* 插入代码 */
            "markdown": function (options) {
                this.insert("* ", "", true);
            }
        },

        /* 插入有序列表 */
        "ol": {
            /* 有序列表捷键 */
            "keyboard": "ctrl+o",

            /* 插入有序列表 */
            "markdown": function (options) {
                this.insert("{$line}. ", "", true);
            }
        },

        /* 引用文本 */
        "blockquote": {
            /* 引用快捷键 */
            "keyboard": "ctrl+q",

            /* 插入代码 */
            "markdown": function (options) {
                this.insert("> ", "", true);
            }
        },

        /* 插入水平分割线 */
        "hr": {
            /* 分割线快捷键 */
            "keyboard": "ctrl+h",

            /* 插入分割线 */
            "markdown": function (options) {
                var range = this.range.get(),
                    start = range.start + range.text.length + 11;

                this.insert(range.text + "\n* * * * *\n");
                this.range.set(start, start);
            }
        },

        /* 全屏编辑 */
        "fullscreen": {
            /* 全屏编辑快捷键 */
            "keyboard": "ctrl+f",

            /* 执行全屏编辑 */
            "markdown": function (options) {
                var $body = $("body"),
                    $editor = $(this.range.textarea).closest(".thinkeditor");

                if ($editor.hasClass("thinkeditor-fullscreen")) {
                    $body.css("overflow", "");
                    $editor.removeClass("thinkeditor-fullscreen");
                } else {
                    $body.css("overflow", "hidden");
                    $editor.addClass("thinkeditor-fullscreen");
                }
            }
        },

        /* 保存数据 */
        "save": {
            /* 保存数据快捷键 */
            "keyboard": "ctrl+s",

            /* 执行全屏编辑 */
            "markdown": function (options) {
                if ($.isFunction(options.onSave)) {
                    options.onSave.call(this.range.textarea);
                }
            }
        },

        /* 文本缩进 */
        "indent": {
            /* 缩进快捷键 */
            "keyboard": "tab",

            /* 插入缩进 */
            "markdown": function (options) {
                var range = this.range.get(), text, start;
                if (range.start) {
                    text = this.range.textarea.value.substring(0, range.start);
                    start = text.lastIndexOf("\n") + 1;
                    if (range.text.length && start != text.length) {
                        this.range.set(start, range.end);
                    }
                }
                this.insert(options.tab, "", true);
            }
        },

        /* 减少缩进 */
        "outdent": {
            /* 减少缩进快捷键 */
            "keyboard": "shift+tab",

            /* 插入代码 */
            "markdown": function (options) {
                var range = this.range.get(), text, start;
                if (range.start) {
                    text = this.range.textarea.value.substring(0, range.start);
                    start = text.lastIndexOf("\n") + 1;
                    if (start != text.length) {
                        range = this.range.set(start, range.end).get();
                    }
                }

                if (range.text.length) {
                    text = range.text.split("\n");
                    for (i in text) {
                        text[i] = text[i].replace(/^((\t)|( {1,4}))/, "");
                    }
                    this.insert(text.join("\n"));
                }
            }
        }
    });

    /**
     * ThinkEditor编辑器默认语言包
     * 默认仅支持英文和简体中文语言包
     * 其他语言包可以通过 $.thinkeditor.laguage() 方法扩展
     */
    $.thinkeditor.language({
        /* 英文语言包 */
        "en-us": {
            /* 工具栏语言 */
            "h1": "H1 (Ctrl+1)",
            "h2": "H2 (Ctrl+2)",
            "h3": "H3 (Ctrl+3)",
            "h4": "H4 (Ctrl+4)",
            "h5": "H5 (Ctrl+5)",
            "h6": "H6 (Ctrl+6)",
            "link": "Link (Ctrl+L)",
            "image": "Image (Ctrl+P)",
            "bold": "Blod (Ctrl+B)",
            "italic": "Italic (Ctrl+I)",
            "code": "Code (Ctrl+D)",
            "ul": "Unordered List (Ctrl+U)",
            "ol": "Ordered List (Ctrl+O)",
            "blockquote": "Blockquote (Ctrl+Q)",
            "hr": "Horizontal Rule (Ctrl+H)",
            "fullscreen": "Full Screen (Ctrl+F)",
            "save": "Save (Ctrl+S)",

            /* 弹出层语言 */
            "ok": "OK",
            "cancel": "Cancel",

            /* 图片插件语言 */
            "image-title": "Insert Image",
            "image-text": "Drag the image to here"
        },

        /* 简体中文语言包 */
        "zh-cn": {
            /* 工具栏语言 */
            "h1": "标题一 (Ctrl+1)",
            "h2": "标题二 (Ctrl+2)",
            "h3": "标题三 (Ctrl+3)",
            "h4": "标题四 (Ctrl+4)",
            "h5": "标题五 (Ctrl+5)",
            "h6": "标题六 (Ctrl+6)",
            "link": "链接 (Ctrl+L)",
            "image": "图片 (Ctrl+P)",
            "bold": "加粗 (Ctrl+B)",
            "italic": "斜体 (Ctrl+I)",
            "code": "代码 (Ctrl+D)",
            "ul": "无序列表 (Ctrl+U)",
            "ol": "有序列表 (Ctrl+O)",
            "blockquote": "引用 (Ctrl+Q)",
            "hr": "分割线 (Ctrl+H)",
            "fullscreen": "全屏编辑 (Ctrl+F)",
            "save": "保存 (Ctrl+S)",

            /* 弹出层语言 */
            "ok": "确定",
            "cancel": "取消",

            /* 图片插件语言 */
            "image-title": "插入图片",
            "image-text": "拖动图片到这里上传"
        }
    });

}(jQuery);
